#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using std::cout;
using std::endl;
using std::vector;
using std::for_each;
using std::mem_fn;
using std::remove_if;
using std::bind;

//mem_fn，函数适配器

class Number
{
public:
    Number(size_t data = 0)
    : _data(data)
    {
    }

    void print() const
    {
        cout << _data << "  ";
    }

    bool isEven() const
    {
        return (0 == _data % 2);
    }

    bool isPrimer() const
    {
        if(1 == _data)
        {
            return false;
        }
        for(size_t idx = 2; idx <= _data/2; ++idx)
        {
            if(0 == _data % idx )
            {
                return false;
            }
        }

        return true;
    }

    ~Number()
    {

    }
private:
    size_t _data;
};
void test()
{
    vector<Number> vec;

    for(size_t idx = 1; idx != 30; ++idx)
    {
        vec.push_back(Number(idx));
    }
    //遍历vector中的元素
    //for_each(vec.begin(), vec.end(), &Number::print); 报错
    for_each(vec.begin(), vec.end(), mem_fn(&Number::print)); 
    //因为成员函数和算法库里的算法(for_each、remove_if)不适配，
    //所以使用成员函数适配器
    //如果print是普通函数则可以直接 print 或 &print
    
    cout<<endl;
    cout<<endl;

    using namespace std::placeholders;
    for_each(vec.begin(), vec.end(), bind(&Number::print, _1));
    //for_each要求的是一元函数，print本身就是一元函数了
    //如果bind绑定了其他参数，则堵死了，迭代器传不进去
    //而bind绑定成员函数时，要传入this指针，但是这里并没有创建对象，怎么传入this指针？
    //用占位符。因为for_each会让迭代器依次传入bind，而且只有一个参数，
    //这个传入的迭代器（注意这里迭代器指向的是一个个Number）就是我们要的this
    
    cout << endl;
    cout << endl;

    cout<<"将所有的偶数都删除"<<endl;
    vec.erase(remove_if(vec.begin(), vec.end(), mem_fn(&Number::isEven)), 
              vec.end());
    for_each(vec.begin(), vec.end(), mem_fn(&Number::print));
    
    cout << endl;
    cout << endl;

    cout<<"将所有的质数删除"<<endl;
    vec.erase(remove_if(vec.begin(), vec.end(), mem_fn(&Number::isPrimer)), 
              vec.end());
    for_each(vec.begin(), vec.end(), mem_fn(&Number::print));
    cout << endl;

}

int main()
{
    test();
    return 0;
}


